﻿using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Optum.SN.Infra.Core.TestBase.Utility;
using Optum.SN.Infra.Core.Dependency.Service;

namespace Optum.SN.Infra.Core.TestBase
{
    /// <summary>
    /// Abstracts external dependencies, so, web service calls maybe mocked for unit tests.
    /// </summary>
    public abstract class MockHttpClientBase : DefaultHttpClient
    {
        /// <summary>
        /// Builds serializer to later generate <see cref="HttpResponseMessage"/> with.
        /// </summary>
        /// <param name="context">Provides <see cref="IServiceContext.DataTransferMedia">media type</see>, used to build serializer.</param>
        public override void SetContext(IServiceContext context)
        {
            Serializer = SerializerBuilder.Build(context.DataTransferMedia);
        }
        /// <summary>
        /// Builds <see cref="HttpResponseMessage"/> with status OK using mock records provided in a subclass.
        /// </summary>
        /// <param name="requestUri">Provides record id, to build response content with.</param>
        /// <returns>Good response message with mock records as content.</returns>
        public override Task<HttpResponseMessage> GetAsync(string requestUri)
        {
            ResponseBuilder responseBuilder = new ResponseBuilder {Serializer = Serializer};
            int recordId;
            int.TryParse(requestUri.Split(@"/".ToCharArray()).Last(), out recordId);

            return Task.FromResult(responseBuilder.BuildGoodRresponse(GetMockRecords(recordId)));
        }
        /// <summary>
        /// Builds <see cref="HttpResponseMessage"/> with status OK, using provided record id.
        /// </summary>
        /// <typeparam name="T">Type of record the id belongs to.</typeparam>
        /// <param name="requestUri">Not used in this mock operation.</param>
        /// <param name="value">Provides the id for the record to hydrate content.  A value of 0 signifies all records of the specified type.</param>
        /// <returns>Hydrated response message.</returns>
        public override Task<HttpResponseMessage> PostAsJsonAsync<T>(string requestUri, T value)
        {
            ResponseBuilder responseBuilder = new ResponseBuilder {Serializer = Serializer};
            return Task.FromResult(responseBuilder.BuildGoodRresponse(GetMockRecords(value)));
        }
        /// <summary>
        /// Gets mock records.
        /// </summary>
        /// <param name="recordId">Mock record id, 0 implies all records.</param>
        /// <returns>Mock records.</returns>
        protected abstract IEntity GetMockRecords(int recordId);
        /// <summary>
        /// Gets mock records.
        /// </summary>
        /// <typeparam name="T">Query type.</typeparam>
        /// <param name="query">Query instance, provides record id.</param>
        /// <returns>Mock records.</returns>
        protected abstract IEntity GetMockRecords<T>(T query);
        /// <summary>
        /// Gets/sets serializer.
        /// </summary>
        private ISerializer Serializer { get; set; }
    }
}